/*****************************************************\
* Copyright (c) 2020 The game2d Authors. All rights reserved.
  Use of this source code is governed by a BSD-style license that can be
  found in the LICENSE file.

* Author:         dzlua - https://gitee.com/dzlua/game2d.git
* Email:          505544956@qq.com
* FileName:       ctrls/control.cc
* Create Time:    2020/03/21 12:29:56
* Description:    /
\****************************************************/
#include "control.h"

namespace g2d {
namespace ctrl {
  Control::Control(bool load_res_on_enter) : Sprite(load_res_on_enter) {}
  Control* Control::parent_ctrl() const { return dynamic_cast<Control*>(parent_); }
  Control* Control::item_ctrl(Uint32 idx) const { return dynamic_cast<Control*>(at(idx));}
  Size Control::test_size() const { return fixed_size_; }
  void Control::set_fixed_size(float w, float h) { fixed_size_.w = w; fixed_size_.h = h; }
  void Control::set_fixed_size(const Size &size) { fixed_size_ = size; }
  Size Control::fixed_size() const { return fixed_size_; }
  void Control::set_disabled_image(TextureData *image) { disabled_image_ = *image; }
  const TextureData& Control::disabled_image() const { return disabled_image_; }
  void Control::set_attribute(const char *name, const char *value) {
    if (strcmp(name, "size") == 0) set_fixed_size(utils::parse_size(value));
    else if (strcmp(name, "width") == 0) fixed_size_.w = utils::parse_float(value);
    else if (strcmp(name, "height") == 0) fixed_size_.h = utils::parse_float(value);
    else if (strcmp(name, "bkimage") == 0) set_image(&utils::parse_image(value));
    else if (strcmp(name, "disabledimage") == 0) set_disabled_image(&utils::parse_image(value));
    else Sprite::set_attribute(name, value);
  }
  void Control::update(Input &inp, Audio &aud) {
    if (enabled_)
      update_control(inp, aud);
    if (visible_)
      update_layout();
  }
  void Control::render(g2d::Renderer &r) {
    if (!visible_) return;
    r.set_clip_rect(&rect_);
    render_color(r);
    render_image(r);
    render_text(r);
    render_border(r);
    GameObject::render(r);
    r.set_clip_rect(0);
  }
  void Control::update_control(Input &inp, Audio &aud) {}
  void Control::update_layout() {}
  void Control::render_color(g2d::Renderer &r) {
    if (back_color_.a > 0) {
      r.set_draw_color(back_color_);
      r.fill_rect(&rect_);
    }
  }
  void Control::render_image(g2d::Renderer &r) {
    if (enabled_) {
      if (!image_.id.empty())
        r.draw_texture(&image_, &rect_);
    } else {
      if (!disabled_image_.id.empty())
        r.draw_texture(&disabled_image_, &rect_);
    }
  }
  void Control::render_text(g2d::Renderer &r) {}
  void Control::render_border(g2d::Renderer &r) {}

  Label::Label(bool load_res_on_enter) : Control(load_res_on_enter) {
    memset(&text_color_, 0, sizeof(text_color_));
    memset(&disabled_text_color_, 0, sizeof(disabled_text_color_));
    memset(&text_padding_, 0, sizeof(text_padding_));
    text_halign_ = HorAlign::Center;
    text_valign_ = VerAlign::Middle;
  }
  void Label::set_font(const char *id) { if (id) font_ = id; }
  const char* Label::font() const { return font_.c_str(); }
  void Label::set_text(const char *text) { if (text) text_ = text; }
  const char* Label::text() const { return text_.c_str(); }
  void Label::set_text_color(const SDL_Color &color) { text_color_ = color; }
  const SDL_Color& Label::text_color() const { return text_color_; }
  void Label::set_disabled_text_color(const SDL_Color &color) { disabled_text_color_ = color; }
  const SDL_Color& Label::disabled_text_color() const { return disabled_text_color_; }

  void Label::set_text_halign(HorAlign align) { text_halign_ = align; }
  HorAlign Label::text_halign() const { return text_halign_; }
  void Label::set_text_valign(VerAlign align) { text_valign_ = align; }
  VerAlign Label::text_valign() const { return text_valign_; }

  void Label::set_text_padding(const SDL_FPoint &padding) { text_padding_ = padding; }
  const SDL_FPoint& Label::text_padding() const { return text_padding_; }
  Size Label::test_size() const {
    if (fixed_size_.w <= 0.f || fixed_size_.h <= 0.f) {
      int w, h;
      g2d_->font().size(font_.c_str(), text_.c_str(), &w, &h);
      Size sz(fixed_size_);
      if (fixed_size_.w <= 0.f) sz.w = (float)w;
      if (fixed_size_.h <= 0.f) sz.h = (float)h;
      return std::move(sz);
    }
    return fixed_size_;
  }
  void Label::set_attribute(const char *name, const char *value) {
    if (strcmp(name, "font") == 0) set_font(value);
    else if (strcmp(name, "text") == 0) set_text(value);
    else if (strcmp(name, "textcolor") == 0) set_text_color(utils::parse_color(value));
    else if (strcmp(name, "disabledtextcolor") == 0) set_disabled_text_color(utils::parse_color(value));
    else if (strcmp(name, "texthalign") == 0) set_text_halign(utils::parse_halign(value));
    else if (strcmp(name, "textvalign") == 0) set_text_valign(utils::parse_valign(value));
    else if (strcmp(name, "textoffset") == 0) set_text_padding(utils::parse_pos(value));
    else Control::set_attribute(name, value);
  }
  void Label::render_text(g2d::Renderer &r) {
    SDL_FRect rc = calculate_text_rect(r);
    if (enabled_) {
      if (text_color_.a > 0) {
        r.draw_text(font_.c_str(), text_.c_str(), text_color_, &rc);
      }
    } else {
      if (disabled_text_color_.a > 0) {
        r.draw_text(font_.c_str(), text_.c_str(), disabled_text_color_, &rc);
      }
    }
  }
  SDL_FRect Label::calculate_text_rect(g2d::Renderer &r) {
    SDL_FRect rc;
    int w, h;
    r.text_size(font_.c_str(), text_.c_str(), &w, &h);
    switch (text_halign_) {
      case HorAlign::Left: rc.x = rect_.x; break;
      case HorAlign::Center: rc.x = rect_.x + (rect_.w-w)/2.f; break;
      case HorAlign::Right: rc.x = rect_.x + rect_.w - w; break;
    }
    switch (text_valign_) {
      case VerAlign::Top: rc.y = rect_.y; break;
      case VerAlign::Middle: rc.y = rect_.y + (rect_.h-h)/2.f; break;
      case VerAlign::Bottom: rc.y = rect_.y + rect_.h - h; break;
    }
    rc.x += text_padding_.x;
    rc.y += text_padding_.y;
    rc.w = w;
    rc.h = h;
    return std::move(rc);
  }

  Button::Button(bool load_res_on_enter) : Label(load_res_on_enter) {
    memset(&hot_text_color_, 0, sizeof(hot_text_color_));
    memset(&pushed_text_color_, 0, sizeof(pushed_text_color_));
    hot_ = pressed_ = false;
  }
  void Button::set_hot_text_color(const SDL_Color &color) { hot_text_color_ = color; }
  const SDL_Color& Button::hot_text_color() const { return hot_text_color_; }
  void Button::set_pushed_text_color(const SDL_Color &color) { pushed_text_color_ = color; }
  const SDL_Color& Button::pushed_text_color() const { return pushed_text_color_; }
  void Button::set_hot_image(TextureData *image) { hot_image_ = *image; }
  const TextureData& Button::hot_image() const { return hot_image_; }
  void Button::set_pushed_image(TextureData *image) { pushed_image_ = *image; }
  const TextureData& Button::pushed_image() const { return pushed_image_; }
  void Button::set_attribute(const char *name, const char *value) {
    if (strcmp(name, "hottextcolor") == 0) set_hot_text_color(utils::parse_color(value));
    else if (strcmp(name, "pushedtextcolor") == 0) set_pushed_text_color(utils::parse_color(value));
    else if (strcmp(name, "hotimage") == 0) set_hot_image(&utils::parse_image(value));
    else if (strcmp(name, "pushedimage") == 0) set_pushed_image(&utils::parse_image(value));
    else Label::set_attribute(name, value);
  }
  void Button::update_control(Input &inp, Audio &aud) {
    auto pt = inp.mouse_point();
    hot_ = pt_in(pt.x, pt.y);
    pressed_ = hot_ && inp.mouse_pressed(SDL_BUTTON_LEFT, false);
    if (hot_ && inp.mouse_pressed(SDL_BUTTON_LEFT)) {
    }
  }
  void Button::render_image(g2d::Renderer &r) {
    if (!enabled_) {
      if (!disabled_image_.id.empty())
        r.draw_texture(&disabled_image_, &rect_);
    } else if (pressed_) {
      if (!pushed_image_.id.empty())
        r.draw_texture(&pushed_image_, &rect_);
    } else if (hot_) {
      if (!hot_image_.id.empty())
        r.draw_texture(&hot_image_, &rect_);
    } else {
      if (!image_.id.empty())
        r.draw_texture(&image_, &rect_);
    }
  }
  void Button::render_text(g2d::Renderer &r) {
    SDL_FRect rc = calculate_text_rect(r);
    if (!enabled_) {
      if (disabled_text_color_.a > 0)
        r.draw_text(font_.c_str(), text_.c_str(), disabled_text_color_, &rc);
    } else if (pressed_) {
      if (pushed_text_color_.a > 0)
        r.draw_text(font_.c_str(), text_.c_str(), pushed_text_color_, &rc);
    } else if (hot_) {
      if (hot_text_color_.a > 0)
        r.draw_text(font_.c_str(), text_.c_str(), hot_text_color_, &rc);
    } else {
      if (text_color_.a > 0)
        r.draw_text(font_.c_str(), text_.c_str(), text_color_, &rc);
    }
  }
} // end namespace ctrl
} // end namespace g2d